package com.mas.session.state;

import jade.domain.FIPAException;
import jade.domain.FIPAAgentManagement.FailureException;
import jade.lang.acl.ACLMessage;

import java.util.Map;

import com.mas.common.AgentUtil;
import com.mas.common.Consts.Response;
import com.mas.session.MonitorSession;
import com.mas.session.Session;
import com.mas.strategey.Proposal;
import com.thoughtworks.xstream.XStream;

public class ProcessIncomingCFP extends AbstractState {

	private XStream xstream;

	public ProcessIncomingCFP(Session session) {
		super(session);
	}

	/**
	 * 1.process the message set new stage <-- WaitingForProposalResState
	 * 
	 * @throws FailureException
	 * 
	 */
	public void processIncomingCFPMsg(ACLMessage message) throws FIPAException {
		AgentUtil.logInfo(session.getAgent(),"ProcessIncomingCFP.processIncomingCFPMsg()");

		String content = message.getContent();

		if (content == null) {
			assignFailureState(message, "message contenct cannot be null");
			return;
		}

		xstream = new XStream();
		Object obj = null;
		try {
			obj = xstream.fromXML(content);
		} catch (Exception e) {
			assignFailureState(message, "Expecting Proposal Object");
			return;
		}

		if (!(obj instanceof Proposal)) {
			assignFailureState(message, "Expecting Proposal Object");
			return;
		}
		Proposal curProposal = (Proposal) obj;

		Map mapResourceAllocator = ((MonitorSession)this.session).getMonitorResourceAgent()
				.getMapResourceAllocator();

		for (int i = 0; i < curProposal.getResourceInfos().length; i++) {
			if (!mapResourceAllocator.containsKey(curProposal
					.getResourceInfos()[i].getResourceName())) {
				assignFailureState(message, "Error, resource:"
						+ curProposal.getResourceInfos()[i] + " not found");
				return;
			}
		}

		callSrategy(curProposal, message);
	}

	private void callSrategy(Proposal curProposal, ACLMessage message) {
		Proposal proposal = new Proposal();
		proposal.setPrice(-1); //mark this proposal as the first time.
		proposal.setResourceInfos(curProposal.getResourceInfos());
		Response response = this.session.getStrategy().decide(proposal);

		if (response == Response.REJECT) {
			RefuseExitState state = (RefuseExitState) this.session
					.assignState(RefuseExitState.class.getName());

			state.setProposal(proposal);
			this.session.setCurrentState(state);
			state.NoAvailableResource(message);

		} else {
			Proposal newProposal = this.session.getStrategy().buildNewProposal(
					proposal);
			ACLMessage reply = message.createReply();

			reply.setContent(xstream.toXML(newProposal));
			reply.setPerformative(ACLMessage.PROPOSE);
//			reply.setReplyWith(session.buildUniqueID());
			this.session.getAgent().send(reply);

			WaitingForProposalResState state = (WaitingForProposalResState) this.session
					.assignState(WaitingForProposalResState.class.getName());

			state.setProposal(newProposal);
			this.session.setCurrentState(state);
			state.waitForProposalResponse(message);

		}
	}

}